/* Orbas:
 *     A open source CORBA Specification implementation from Huihoo.
 *
 * Copyright 2002-2003 Huihoo.org, Inc. All Right Reserved.
 *
 * This software is licensed under LGPL license.
 * See terms of license at gnu.org.
 *
 * For more information, visit:
 *
 * http://www.huihoo.org/orbas
 */



package org.huihoo.orbas.orb.giop;

/**
 * <p>Description: </p>
 * Client side GIOP implementation.
 * <p>Copyright (c) 2002,2003</p>
 * <p>Company: <a href="http://www.huihoo.org/">huihoo.org</a></p>
 * @author <a href="http://www.huihoo.org/~mep">mep(mep@huihoo.com)</a>
 * @see <a href="http://www.huihoo.org/orbas">http://www.huihoo.org/orbas</a>
 * @version 1.0
 */


import org.huihoo.orbas.orb.cdr.*;
//import org.omg.GIOP.*;
import org.huihoo.orbas.orb.protocols.Transport;
import org.huihoo.orbas.orb.protocols.Channel;
//import org.omg.IOP.*;
import org.omg.IOP.ServiceContext;

public class GiopClientWorker extends GiopWorker
                        implements org.huihoo.orbas.orb.ClientWorker {
    
    protected Transport transport;
    org.huihoo.orbas.orb.protocols.TargetAddress target;

    int requestId;
    int version;
    
    public GiopClientWorker(org.omg.CORBA.ORB orb, int version) {
        requestId = 0;
        this.orb = orb;
        this.version = version;
    }
    
    public int getRequestId() {
        return ++requestId;
    }
    
    public CDROutputStream createRequest(org.huihoo.orbas.orb.protocols.TargetAddress target,
                                         org.omg.GIOP.TargetAddress targetObject,
                                         String the_operation,
                                         boolean responseExpected) {
                                            
        this.target = target;
//        this.transport = null;
        
        CDROutputStream out = new CDROutputStream(orb);
        
        switch(version) {
            case 10:

                org.omg.GIOP.RequestHeader_1_0 request10 = 
                        new org.omg.GIOP.RequestHeader_1_0();
                        
                request10.request_id = getRequestId();
                request10.response_expected = responseExpected;
                
                if( targetObject.discriminator() != org.omg.GIOP.KeyAddr.value ) {
                    //error?
                }
                
                request10.object_key = targetObject.object_key();
                request10.operation = the_operation;
                request10.requesting_principal = new byte[0];
                request10.service_context = new org.omg.IOP.ServiceContext[0];
                
                org.omg.GIOP.RequestHeader_1_0Helper.write(out, request10);
                
                break;
                
            case 11:
            
                org.omg.GIOP.RequestHeader_1_1 request11 = 
                        new org.omg.GIOP.RequestHeader_1_1();
                        
                request11.request_id = getRequestId();
                request11.response_expected = responseExpected;
                
                if( targetObject.discriminator() != org.omg.GIOP.KeyAddr.value ) {
                    //error?
                }
                
                request11.object_key = targetObject.object_key();
                request11.operation = the_operation;
                request11.requesting_principal = new byte[0];
                request11.service_context = new org.omg.IOP.ServiceContext[0];
                request11.reserved = new byte[3];
                
                org.omg.GIOP.RequestHeader_1_1Helper.write(out, request11);

                break;
                
            case 12:

                org.omg.GIOP.RequestHeader_1_2 request12 = 
                        new org.omg.GIOP.RequestHeader_1_2();
                        
                request12.request_id = getRequestId();
                request12.response_flags = 0x01;
                request12.reserved = new byte[3];
                
                request12.target = targetObject;
                request12.operation = the_operation;
                request12.service_context = new org.omg.IOP.ServiceContext[0];
                
                org.omg.GIOP.RequestHeader_1_2Helper.write(out, request12);

                break;
                
            default:
                //error
        }
        
        return out;
    }
    
    public CDRInputStream invoke(org.omg.CORBA.portable.OutputStream os)
        throws 
        org.omg.CORBA.portable.ApplicationException,
        org.omg.CORBA.portable.RemarshalException {
        
        CDROutputStream headerOut = new CDROutputStream(orb);
        CDROutputStream bodyOut = (CDROutputStream)os;
        
        org.omg.GIOP.MessageHeader_1_1 messageHeader10 = 
                new org.omg.GIOP.MessageHeader_1_1();
        
        messageHeader10.magic = new char[4];
        messageHeader10.magic[0] = 'G';
        messageHeader10.magic[1] = 'I';
        messageHeader10.magic[2] = 'O';
        messageHeader10.magic[3] = 'P';
        messageHeader10.GIOP_version = new org.omg.GIOP.Version();
        messageHeader10.GIOP_version.major = 1;
        messageHeader10.GIOP_version.minor = (byte)(version - 10);
        
        if( version == 10 ) {
            messageHeader10.flags = 0; //big endian
        }
        else {
            messageHeader10.flags = 0x0;
        }
        
        messageHeader10.message_type = org.omg.GIOP.MsgType_1_0._Request;
        messageHeader10.message_size = bodyOut.getLength() + 1;
        
        org.omg.GIOP.MessageHeader_1_1Helper.write(headerOut,messageHeader10);
        
        headerOut.write_octet_array(bodyOut.getBuffer(), 0, bodyOut.getLength());
        //write out GIOP header
        
        
        
        CDRInputStream ret = null;
        try {
            
            write(headerOut);
            
            ret = read();
            //check if it is a location forward
        }
        catch (java.io.IOException e) {
            e.printStackTrace();
        }
        
        headerOut = null;
        
        return ret;
    }
    
    public void invokeOneway(org.omg.CORBA.portable.OutputStream os) {
        
    }
    
    public CDROutputStream createLocateRequest(org.huihoo.orbas.orb.protocols.TargetAddress target) {
        CDROutputStream out = new CDROutputStream(orb);
        
        return out;
    }
    
    public Transport getTransport() {
        //initialize the channel
        if(transport == null && orb instanceof org.huihoo.orbas.orb.ORB) {
            org.huihoo.orbas.orb.ORB huiOrb =
                    (org.huihoo.orbas.orb.ORB)orb;

//              transport = target.initialChannel().setup();
            transport = huiOrb.getTransportsPool().getTransport(target);
        }
       
        return transport;
    }
    
    public void setTransport(Transport t) {
        transport = t;
    }

}